package solver

import (
	"fmt"
	"log"
)

func (g *Grid) LastOneHouse(house House) (used bool) {
	if house.solvedCount != 8 {
		return
	}

	for _, cell := range house.cells {
		if cell.solved() {
			continue
		}
		if cell.cands.Count() == 0 {
			fmt.Println(house.solvedCount, house.cells)
			g.PrintGrid()
			fmt.Println(g.GivensValues())

		}
		value := toValue(cell.cands.GetList()[0])
		//fmt.Println(cell, house.kind, house.solvedCount, house.cells)
		g.solveOneCell(cell.rowNum, cell.colNum, value)

		log.Printf("r%vc%v %v %v Last One", cell.rowNum, cell.colNum, value, house.KindName())
		used = true
		return
	}
	return
}

func (g *Grid) solveOneCell(rowNum int, colNum int, value int) {
	g.cells[rowNum][colNum].setValue(value)
	g.rows[rowNum].solvedCount += 1
	g.cols[colNum].solvedCount += 1
	boxNum, cellNum := calcBoxAndCellNum(rowNum, colNum)
	g.boxes[boxNum].solvedCount += 1
	g.solvedCount += 1
	clearupHouse(g.rows[rowNum], colNum)
	clearupHouse(g.cols[colNum], rowNum)
	clearupHouse(g.boxes[boxNum], cellNum)
}

/*
	func (g *Grid) LastOne() (used bool) {
		return g.doStrategy(g.LastOneHouse)
	}
*/
func (g *Grid) LastOneBox() (used bool) {
	for _, box := range g.boxes {
		if g.LastOneHouse(box) {
			return true
		}
	}
	return false
}

func (g *Grid) LastOneRow() (used bool) {
	for _, row := range g.rows {
		if g.LastOneHouse(row) {
			return true
		}
	}
	return false
}

func (g *Grid) LastOneCol() (used bool) {
	for _, col := range g.cols {
		if g.LastOneHouse(col) {
			return true
		}
	}
	return false
}

func (g *Grid) HiddenSingleHouse(house House) (used bool) {
	for cand := 0; cand < 9; cand++ {
		var solved *Cell
		count := 0
		for _, cell := range house.cells {
			if cell.solved() {
				continue
			}
			if cell.cands.Has(cand) {
				count++
				solved = cell
			}
		}
		if count != 1 {
			continue
		}
		value := toValue(cand)
		g.solveOneCell(solved.rowNum, solved.colNum, value)
		log.Printf("r%vc%v %v %v Hidden Single", solved.rowNum, solved.colNum, value,
			house.KindName())
		return true
	}

	return
}

/*
	func (g *Grid) HiddenSingleHouse(house House) (used bool) {
		candCells, candCounts := sumupCandCells(house)
		for cand, counts := range candCounts {
			if counts != 1 {
				continue
			}
			for cellNum, candCell := range candCells[cand] {
				if !candCell {
					continue
				}
				solved := house.cells[cellNum]
				g.solveOneCell(solved.rowNum, solved.colNum, cand+1)
				log.Printf("r%vc%v %v %v Hidden Single", solved.rowNum, solved.colNum, cand+1,
					house.KindName())
				return true
			}
		}
		return
	}
*/
func (g *Grid) HiddenSingleRow() (used bool) {
	for _, row := range g.rows {
		if g.HiddenSingleHouse(row) {
			return true
		}
	}
	return false
}

func (g *Grid) HiddenSingleCol() (used bool) {
	for _, col := range g.cols {
		if g.HiddenSingleHouse(col) {
			return true
		}
	}
	return false
}

func (g *Grid) HiddenSingleBox() (used bool) {
	for _, box := range g.boxes {
		if g.HiddenSingleHouse(box) {
			return true
		}
	}
	return false
}

func (g *Grid) NakedSingle() (used bool) {
	for rowNum, row := range g.rows {
		for colNum, cell := range row.cells {
			if cell.solved() || cell.cands.Count() != 1 {
				continue
			}
			value := toValue(cell.cands.GetList()[0])
			g.solveOneCell(rowNum, colNum, value)
			log.Printf("r%vc%v %v %v", rowNum, colNum, value, "Naked Single")
			return true
		}
	}
	return false
}

//*/
